//
// Created by buyongjiu on 2024/4/20.
//

#include <iostream>
#include "../include/NFA.h"

int NFA::createNFA(const Grammar &G) {
    auto p = new NFA_struct(START, G.grammar_type);
    this->Structs.push_back(p);
    this->nameToStruct[G.grammar_type] = p;
    this->state.insert(G.grammar_type);

    // 此处建立一个终止状态，让本来的所有终结符指向这个状态
    p = new NFA_struct(END, "END");
    this->Structs.push_back(p);
    this->nameToStruct["END"] = p;
    this->state.insert("END");
    //遍历对应部分文法
    for(auto& gs:G.grammar) {
        if(this->state.find(gs.left) == this->state.end()){
            auto temp = new NFA_struct(NORMAL, gs.left);
            this->Structs.push_back(temp);
            this->nameToStruct[gs.left] = temp;
            this->state.insert(gs.left);
        }

        if(gs.right.second.empty()){
            this->nameToStruct[gs.left]->addEdge(gs.right.first, "END");
        }
        else {
            if(this->state.find(gs.right.second) == this->state.end()){
                auto q = new NFA_struct(NORMAL, gs.right.second);
                this->Structs.push_back(q);
                this->nameToStruct[gs.right.second] = q;
                this->state.insert(gs.right.second);
            }
            this->nameToStruct[gs.left]->addEdge(gs.right.first, gs.right.second);
        }
        this->alphabet.insert(gs.right.first);
    }
    return 0;
}

void NFA::PrintNFA() {
    std::cout << "NFA Information:" << std::endl;
    std::cout << "Alphabet: ";
    for (const auto& symbol : alphabet) {
        std::cout << symbol << " ";
    }
    std::cout << std::endl;

    std::cout << "NFA States:" << std::endl;
    for (const auto& entry : nameToStruct) {
        std::cout << "State: " << entry.first << std::endl;
        std::cout << "Type: " << entry.second->type << std::endl;
        std::cout << "Transitions:" << std::endl;
        for (const auto& transition : entry.second->gotoState) {
            std::cout << "Input: " << transition.first << " Next States: ";
            for (const auto& nextState : transition.second) {
                std::cout << nextState << " ";
            }
            std::cout << std::endl;
        }
    }
}


NFA_struct::NFA_struct(Type_t t, std::string nowstate) {
    this->type = t;
    this->nowState = nowstate;
}

int NFA_struct::addEdge(std::string input, std::string next) {
    this->gotoState[input].insert(next);
    return 0;
}
